<template>
  <Pagination
    :total="options.total"
    :pageSize="options.pageSize"
    :pageNumber="options.pageNumber"
    @pageChange="onPageChange"
    v-bind="options.attributes"
    v-on="options.events"
  ></Pagination>
</template>

<script setup lang="ts">
import {defineModel, onBeforeMount, type PropType, watch,} from "vue";
import _ from "lodash";
import ArkPaginationOptionsDefault, {ArkPaginationOptions} from "./ArkPaginationOptions";

/** 接口（组件的接口）。包括：defineOptions、defineModel、defineProps、defineEmits、defineExpose、defineSlots */
const options = defineModel("options", {
  type: Object as PropType<ArkPaginationOptions>,
  default: () => ArkPaginationOptionsDefault
});

/** 本地状态 (本地的响应式 property)。包括：ref、computed */

/** 事件（通过响应式事件触发的回调）。包括：watch */
watch(
  () => {
    return options.value.pageSize;
  },
  () => {
    if (options.value.onPageSizeChange) {
      options.value.onPageSizeChange(options.value.pageSize);
    }

    if (options.value.afterPageSizeChange) {
      options.value.afterPageSizeChange(options.value.pageSize);
    }
  },
);


watch(
  () => {
    return options.value.pageNumber;
  },
  () => {
    if (options.value.onPageNumberChange) {
      options.value.onPageNumberChange(options.value.pageNumber);
    }

    if (options.value.afterPageNumberChange) {
      options.value.afterPageNumberChange(options.value.pageNumber);
    }
  },
);
/** 生命周期钩子（按照它们被调用的顺序）。包括：onBeforeMount、onMounted、onBeforeUpdate、onUpdated、onBeforeUnmount、onUnmounted */
onBeforeMount(() => {
  init();
});

/** 非响应式的 property (不依赖响应系统的实例 property)。包括：常规函数 */
const init = () => {
  _.defaultsDeep(options.value, ArkPaginationOptionsDefault);
};

const onPageChange = (e) => {
  const newPageSize = e.pageSize;
  const newPageNumber = e.pageNumber;

  const oldPageSize = options.value.pageSize;
  const oldPageNumber = options.value.pageNumber;

  // 每页条数改变
  if (newPageSize !== oldPageSize) {
    options.value.pageSize = newPageSize;
    options.value.pageNumber = newPageNumber;
    return;
  }

  // 当前页码改变
  if (newPageNumber !== oldPageNumber) {
    /**
     * ⚠️ ⚠️ ⚠️ ⚠️
     * 注意：这里不能直接赋值 options.value.pageNumber = newPageNumber
     * 作用：避免在“分页器自动纠正页码到最后一页”时，误触发额外的翻页逻辑
     *
     * 用户主动操作（正常分页逻辑）：
     * - 假设有 total = 45 条数据，pageSize = 10，总页数就是 5 页。
     *  - 用户点 第 3 页 → 正常行为 → pageNumber = 3
     *  - 用户点 第 5 页 → 正常行为 → pageNumber = 5
     *
     * 自动纠正操作（用户没有点击分页器，但是分页器自己把页码改了）：
     * - 经典场景：当前页码大于最大页码，组件就会自动把当前页码跳到最后一页
     * - 假设有 total = 45，pageSize = 10，oldPageNumber = 5（第 5 页）。页码范围是 1 ~ 5
     * - 删除了很多数据，现在只剩 total = 35，重新算最大页数：newMaxPageNumber = ceil(35 / 10) = 4，但此时 oldPageNumber = 5，已经超过最大页数
     * - 分页器会自动把页码从 5 → 4（最后一页），就叫 自动纠正到最后一页
     *
     * 如果我们直接赋值，会把这个“自动纠正”当作“用户主动点击第 4 页”，
     * 可能导致多一次无意义的请求。
     *
     * 所以：当 newPageNumber 正好等于新的最大页码，并且小于旧页码时，
     * 说明这是分页器的自动行为 -> 不需要再更新。
     */

      // 判断是不是被组件设置为了最后一页
    const total = options.value.total;
    if (!_.isNil(total)) {
      const newMaxPageNumber = Math.ceil(total / newPageSize);

      // 如果 新的页码 = 新的最大页码，而且 新的页码 < 旧的页码，说明被组件设置为了最后一页
      if (newPageNumber === newMaxPageNumber && newPageNumber < oldPageNumber) {
        return;
      }
    }
    options.value.pageNumber = newPageNumber;
  }
};

/** 其它 */
</script>

<style scoped></style>
